iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
1
自我挑戰組

Wordpress 外掛開發系列 第 18

「Wordpress 外掛開發」建立REST API以及避免原生的設計造成零時差攻擊 - WP-JSON

  • 分享至 

  • xImage
  •  

中秋節可是我沒有烤肉吃

今天要提到Rest Api,大部分都可以知道在其他後端的語言之中,建立一個rest是滿容易的事情,可是你知道嗎?wordpress原生其實就有提供rest了,使用的方式是endpoin來做連接,不只可以收發request,也可以做到授權來做權限判斷,而在這一些經由http的過程之中,我們更需要了解那些基礎的回傳號碼是什麼。

狀態代碼

Status Code Description

  • 2xx Request 成功
  • 3xx Request 重新導向
  • 4xx Request 客戶端錯誤
  • 5xx Request 伺服器出錯

我們主要去訴求的,就是在搭建api中,能夠做到CRUD的功能,必且在撰寫的原則中需要遵守五個規則,在寫這個主題時,我是相信大部分的人對於這一些是有基礎的了解,如果還是有不懂的地方,可以參考官方網站做的http API寫的,滿詳細可以讓人從最初的http request到深入收發的使用。

  • Uniform insterface
  • client-server
  • stateless
  • cacheable
  • layered system

wordpress 提供的

wordpress對於你以post或是page的方式建立的資訊,都有相對應的Api可以去使用到,而我們主要使用的,就是w-json/v2來製作,而這一個根目錄,也是可以來查詢你的函式是否有增加成功,而對於預設的這一些API,與一般使用無差異,是可以不用特別去刪除,反正大家都可以看見你的網頁,除非有特定的漏洞會被攻擊,這樣才需要更加注意。

我們在測試endpoint有很多好的工具可以來使用,如果直接使用chrome會接到沒有排序過的json,是會頭昏眼花,建議是可以抓一些觀看json的套件在你的瀏覽器上,chrome是可以靠裝其他套件來完成看得更清楚,而其餘的瀏覽器就不清楚了,這邊推薦postman或是有json viewer這類的擴充元件可以讓回傳的結果更加正常。

而上述說到的原生api,其實都與正常使用一樣,如果你沒有登入就看不到的內容,在沒有授權的情況之下,是會回傳400給你寫著rest_invaluid_param,你可以試著寫寫看嘗試去發給locahost一個原生的api,並且會被回絕。

curl -X GET http://localhost/wp-json/wp/v2/posts?status=draft

那其實我們有個最簡單的方式,就是在發送的request中,發送自己的帳號密碼,不過這個動作請在測試之中做就好了,在正式主機上會有暴露密碼的風險,github上是有著basic auth來對wordpress endpoint做測試,對於測試環境下來說非常好用,可以參考 basic auth,basic auth單純地將你的帳號密碼每一次都寄出來做到授權,這個只適合在測試階段使用,如果是在正式機室得使用像是金鑰這些更安全的方式來設置。

建立自己的endpoints

只要是關於wordpress的相關功能,基本上都能依靠rest Api來做拓展,一個隨時都能將不錯的資料傳送正確的位置還滿吸引人的吧?我們在製作自己的endpoint時,只需要註冊後寫著就可以使用了,我們將會註冊一段回傳正確語言的訊息,而api的名稱就是phrase


function prefix_get_endpoint_phrase() { 
    return rest_ensure_response( 'Hello World, this is the WordPress REST API' );
}
 

function prefix_register_example_routes() {
    register_rest_route( 'hello-world/v2', '/phrase', array(
        'methods'  => WP_REST_Server::READABLE,
        'callback' => 'prefix_get_endpoint_phrase',
    ) );
}
 
add_action( 'rest_api_init', 'prefix_register_example_routes' );

我們這樣就可以簡單地顯示我們需要的資料,並且將我們所需的內容及相關篩選,寫在回傳的資訊之中,在於wp-json/v2之中是可以查看我們的example_routes是否有正確執行,而近一步要去測試api是否有錯誤,去對著相對應的api做get就可以看見結果

http://localhost/wp-json/hello-world/v1/phrase 

那其實這邊再接其他的參數與我們說之前說到的安全性息息相關,需要做認證,或是將輸入的與輸出的結果做sanitize,都是很必要的。

請別這樣寫,可能有被攻擊垮的可能性

而最後,Wordpress是否有可能因為API的關係,成功資安的缺口,其實這是得取決於自己撰寫的習慣,Api提供的資訊都是在於wordpress本身就已經公開(public)的狀態,所以與點選無異,如果你是rss也是可以拉得到,但有危險的地方就是多了好幾段攻擊的窗口,從安全的角度來看是給駭客們有更多的方式可以去嘗試,不過現在倒是沒有對於api的大問題發現,所以現階段不是很需要擔心可以好好使用它,但如果你還是對它不放心,或許你可以參考一下下面的filter,可以將api停用。

add_filter('rest_enabled', '_return_false');
add_filter('rest_jsonp_enabled', '_return_false');

不過因為wordpress在製作因為各個hook習習相關,在5.0發行之前,曾經是有個對於update的大問題,/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php中出了以id去取得第二個參數的滲透,使用update_item_permissions_check來做做存在id的漏洞,製造逾越權限可以執行update_item去更改ID,而這邊更改的ID其實非常危險。

大部分做sanitize來拉,都是在api的部分,但被注入惡意程式碼後,你在進到頁面如果沒有sanitize你呼叫的object,資料可能當場就再見,重則你連Server的權限都會被抹掉,甚至可以直接下載一些惡意程式做植入,不過在4.7.2之後就沒這個問題了,所以你在判斷權限的部分,你要避免下方的寫法,以防被時差攻擊。

我們初步寫入簡單取得post,而wordpress建立id的方式都是以全部數字為主,而以id注入非數字的字串,則int轉換結果會讓post有艘讓出節果

$post = get_psot($request['id']);
$this->check_update_permission($post);

$id = (int) $request['id'];

id會被轉換後,在其他函式可以被搜尋到就出現了漏洞,就是因為wordpress的編排id都是數字的關係,不過對於做交互比對是可以抵掉大部分的問題,並且在輸入口的地方,做好每一個型別是否正確,以及sainitze每一個輸入的問題,更可以去避免這種無妄之災。

reference

Routes and Endpoints
WordPress REST API and the Security Worries
Basic-auth
Custom REST API endpoint with authentication
How do I use this plugin with Custom Endpoints?
Creating Custom Endpoints for the WordPress REST API
API 是什麼? RESTful API 又是什麼?


上一篇
「Wordpress 外掛開發」版本控制與後續維護
下一篇
「Wordpress 外掛開發」商品限定VVIP,缺了些東西還是可以讓人入侵看光
系列文
Wordpress 外掛開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言